

/**							 @file Main.cpp
						    Arquivo Principal

/*========================================================================*/

#include <GL\gl.h>


/** @mainpage TODO NOME DO TRABALHO

	@section intro_sec Introdução
	TODO Escrever introdução
	
	@section ambiente_sec Ambiente de Desenvolvimento
	TODO Escrever sobre o ambiente de desenvolvimento
	
	@section compilacao_sec Compilação
	TODO Escrever instruções de como compilar o programa
	
	@section execucao_sec Execução
	TODO Escrever instruções de como executar o programa      

 @author Pablo Roberlan Manke Barcellos
 @author Pablo Roberlan Manke Barcellos
 @author Pablo Roberlan Manke Barcellos
 @author Pablo Roberlan Manke Barcellos
 @author Pablo Roberlan Manke Barcellos
 @date Semestre: 2008/01

==========================================================================*/




/*================================= Includes =============================*/

#include <stdio.h>
#include <windows.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <math.h>


/*================================= Defines ==============================*/

/* Esconde a janela do console */
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )



#define TAM_BLOCO 100          /** Tamanho do bloco da parede. */ // TODO Trocar o nome
#define PASSO 10              	    
#define NUMERO_DE_TEXTURAS 4   /** Número de texturas que serão lidas no programa.            */
#define LINHAS 32              /** Numero de linhas da matriz que representa o mapa.          */
#define COLUNAS 15             /** Numero de colunas da matriz que representa o mapa.        */

#define PAREDE1 1
#define PAREDE2 2
#define CADEIRA 3



/*================================== Global ==============================*/

GLfloat player_x = TAM_BLOCO; /** Coordenada X do jogador            */
GLfloat player_z = TAM_BLOCO; /** Coordenada Z do jogador            */
GLfloat player_y = -100;        /** Coordenada Y do jogador ( Altura ) */

GLfloat movimento_x = PASSO; 
GLfloat movimento_z = 0;

GLint angulo = 0;

GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat mat_amarelo[] = {0.8, 0.8, 0.1, 1.0};
GLfloat mat_verde[] = { 0.1, 0.6, 0.1, 1.0 };
GLfloat mat_vermelho[] = { 0.7, 0.1, 0.1, 1.0 };
GLfloat light_position[] = { 0.0, 500.0, 0.0, 1.0 };
GLfloat luz_branca[] = { 1.0,1.0,1.0,1.0 };
GLfloat lmodel_ambient[] = { 0.6,0.6,0.6,1.0 };

GLfloat x_anterior = PASSO;
GLfloat y_anterior = 0;


/**
        Matriz que representa o mapa.

        O número 1 representa uma parede paralela e o numero 2 uma parede ortogonal,
        ou o contrário...
 */

GLint mapa[LINHAS][COLUNAS] = { 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,
                                1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,3,0,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,2,2,2,2,2,2,2,2,2,2,2,1,
                                1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,2,2,2,2,2,2,2,2,2,2,2,1,
                                1,0,0,4,0,0,4,0,0,0,1,0,0,0,1,
                                1,0,0,4,0,0,4,0,0,0,1,0,0,0,1,
                                1,0,0,4,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,2,2,2,2,2,0,2,2,2,2,2,1,
                                1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,1,0,0,0,0,4,0,0,0,0,0,1,
                                1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,1,0,0,0,3,0,0,0,0,0,0,1,
                                1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
                                1,0,0,2,2,0,2,2,0,2,2,2,0,2,1,
                                1,0,0,1,0,0,0,1,0,1,0,0,0,0,1,
                                1,0,0,1,0,0,0,1,0,1,0,0,0,0,1,
                                1,0,0,1,0,0,0,1,0,1,0,0,0,0,1,
                                1,0,0,1,0,0,0,1,0,1,0,0,0,0,1,
                                1,0,0,0,0,0,0,0,0,1,0,2,2,2,1,
                                1,0,0,2,2,2,2,2,2,1,0,1,0,0,1,
                                1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,
                                1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,
                                1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,
                                1,2,2,2,2,2,2,2,2,2,2,2,2,2,1 };

GLint teto[LINHAS][COLUNAS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,2,2,0,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
0,2,2,0,2,2,0,2,2,2,0,2,2,2,0,
0,2,2,0,2,2,0,2,2,2,0,2,2,2,0,
0,2,2,0,2,2,2,2,2,2,2,2,2,2,0,
0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,
0,2,2,2,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
0,2,2,0,0,2,0,0,2,0,0,0,2,0,0,
0,2,2,0,2,2,2,0,0,0,2,2,2,2,0,
0,2,2,0,2,2,2,0,0,0,2,2,2,2,0,
0,2,2,0,2,2,2,0,0,0,2,2,2,2,0,
0,2,2,0,2,2,2,0,0,0,2,2,2,2,0,
0,2,2,2,2,2,2,2,2,0,2,0,0,0,0,
0,2,2,0,0,0,0,0,0,0,2,0,2,2,0,
0,2,2,2,2,0,1,1,1,0,2,0,2,2,0,
0,2,2,2,2,0,1,1,1,0,2,0,2,2,0,
0,2,2,2,2,2,1,1,1,0,2,2,2,2,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};


GLint chao[LINHAS][COLUNAS] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
		0,2,2,0,3,3,3,3,3,3,3,3,3,3,0,
		0,2,2,3,3,3,3,3,3,3,3,3,3,3,0,
		0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
		0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
		0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
		0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,
		0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
		0,2,2,0,2,2,0,2,2,2,0,3,3,3,0,
		0,2,2,0,2,2,0,2,2,2,0,3,3,3,0,
		0,2,2,0,2,2,2,2,2,2,3,3,3,3,0,
		0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,
		0,2,2,2,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,1,1,1,1,1,1,1,1,1,1,0,
		0,2,2,0,0,2,0,0,2,0,0,0,2,0,0,
		0,2,2,0,2,2,2,0,2,0,2,2,2,2,0,
		0,2,2,0,2,2,2,0,2,0,2,2,2,2,0,
		0,2,2,0,2,2,2,0,2,0,2,2,2,2,0,
		0,2,2,0,2,2,2,0,2,0,2,2,2,2,0,
		0,2,2,2,2,2,2,2,2,0,2,0,0,0,0,
		0,2,2,0,0,0,0,0,0,0,2,0,2,2,0,
		0,3,3,3,3,0,1,1,1,0,2,0,2,2,0,
		0,3,3,3,3,0,1,1,1,0,2,0,2,2,0,
		0,3,3,3,3,3,1,1,1,0,2,2,2,2,0,
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

GLuint idTextura[ NUMERO_DE_TEXTURAS ];

#include "Cadeira.cpp"
#include "Parede.cpp"
#include "Textura.cpp"
#include "Parede_corredor1_sala1.cpp"

//#include "tgaload.cpp"
//#include "Cadeira.h"


/*=============================== Estruturas =============================*/

/**
	Enumeração usada para definir um tipo de dado booleano.

	Com este novo tipo pode-se declarar variáveis booleanas, que recebem 
	os valores <i>true</i> e <i>false</i>.
*/





/*========================= Função escrever_texto ========================*/

/**
	Função utilizada para escrever algum texto na tela.

	@param fonte é a fonte do texto. Podendo ser GLUT_STROKE_ROMAN
	ou GLUT_STROKE_MONO_ROMAN.
	@param texto é o texto que será escrito na tela.
*/

void escrever_texto( void *fonte, char *texto )
{
	while( *texto )
		glutStrokeCharacter( fonte,*texto++ );
}





/*============================= Função pode_mover ========================*/

/**
	Função que verifica se um movimento pode ser feiro ou não.

	A função testa se o movimento pretendido corresponde a uma posição zero
	na matriz. Caso corresponda ao zero o movimento é possivel.

	@param pos_x :TODO: Terminar...
        @param vet_x: posição pretendida.
*/

int pode_mover( float pos_x, float pos_z, float vet_x, float vet_z )
{
	float mundo_x = pos_x + vet_x ;
	float mundo_z = pos_z + vet_z ;

	int ind_x = (int) ( ( mundo_x + TAM_BLOCO/2 ) / TAM_BLOCO );
	int ind_z = (int) ( ( mundo_z + TAM_BLOCO/2 ) / TAM_BLOCO );

	if( mapa[ind_x][ind_z] ) 
		return false;
	else 
		return true;
}



/*=========================== Função inicializar =========================*/

/**
	Função para inicializar as variáveis.

	Define os valores iniciais das funções usadas pelo programa.
*/

void inicializar ( void )
{
	glShadeModel( GL_SMOOTH );

	glClearColor( 0.3, 0.6, 0.8, 0.5 );
 
	//glLightfv( GL_LIGHT0, GL_POSITION, light_position );
	glLightfv( GL_LIGHT0, GL_DIFFUSE, luz_branca );
	glLightfv( GL_LIGHT0, GL_SPECULAR, luz_branca );
	//glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );

	//glEnable( GL_LIGHTING );
	//glEnable( GL_LIGHT0 );

	//Especifica sistema de coordenadas de projecao
	glMatrixMode( GL_PROJECTION );
	// Inicializa sistema de coordenadas de projecao
	glLoadIdentity();

	//Especifica a projecao perspectiva
	gluPerspective( 90,1,0.1,3000 );

	//Especifica sistema de coordenadas do modelo
	glMatrixMode( GL_MODELVIEW );

	// Inicializa sistema de coordenadas de projecao
	//glLoadIdentity();

	glEnable( GL_DEPTH_TEST );


	// Comandos de inicialização para textura
	ler_textura_TGA( "imagem1.tga", 0 );
	ler_textura_TGA( "imagem2.tga", 1 );
	ler_textura_TGA( "imagem3.tga", 2 );
	ler_textura_TGA( "imagem4.tga", 3 );
        
}



/*========================= Função desenhar_bloco ========================*/

/**
        Desenha e aplica uma textura a um bloco.

	Função utilizada para desenhar e aplicar a textura aos seis quadrados, que formaram
        os blocos usados para as paredes, teto, etc. 

        @param altura é a altura do bloco.
        @param largura é a largura do bloco.
        @param profundidade é a profundidade do bloco.
*/

void desenhar_bloco( GLfloat altura, GLfloat largura, GLfloat profundidade )
{
     glBegin( GL_QUADS );
     
     // Face frontal
    /* glTexCoord2f(0.0f, 0.0f);      glVertex3f(-largura, -altura,  profundidade);
     glTexCoord2f(largura, 0.0f);   glVertex3f( largura, -altura,  profundidade);
     glTexCoord2f(largura, altura); glVertex3f( largura,  altura,  profundidade);
	 glTexCoord2f(0.0f, altura);    glVertex3f(-largura,  altura,  profundidade);*/
	 
     glTexCoord2f(0.0f, 0.0f); glVertex3f(-largura, -altura,  profundidade);
     glTexCoord2f(1.0f, 0.0f); glVertex3f( largura, -altura,  profundidade);
     glTexCoord2f(1.0f, 1.0f); glVertex3f( largura,  altura,  profundidade);
     glTexCoord2f(0.0f, 1.0f); glVertex3f(-largura,  altura,  profundidade);
         
     // Face posterior
     glTexCoord2f(1.0f, 0.0f); glVertex3f(-largura, -altura, -profundidade);
     glTexCoord2f(1.0f, 1.0f); glVertex3f(-largura,  altura, -profundidade);
     glTexCoord2f(0.0f, 1.0f); glVertex3f( largura,  altura, -profundidade);
     glTexCoord2f(0.0f, 0.0f); glVertex3f( largura, -altura, -profundidade);

     // Face superior
     glTexCoord2f(0.0f, 1.0f); glVertex3f(-largura,  altura, -profundidade);
     glTexCoord2f(0.0f, 0.0f); glVertex3f(-largura,  altura,  profundidade);
     glTexCoord2f(1.0f, 0.0f); glVertex3f( largura,  altura,  profundidade);
     glTexCoord2f(1.0f, 1.0f); glVertex3f( largura,  altura, -profundidade);

     // Face inferior
     glTexCoord2f(1.0f, 1.0f); glVertex3f(-largura, -altura, -profundidade);
     glTexCoord2f(0.0f, 1.0f); glVertex3f( largura, -altura, -profundidade);
     glTexCoord2f(0.0f, 0.0f); glVertex3f( largura, -altura,  profundidade);
     glTexCoord2f(1.0f, 0.0f); glVertex3f(-largura, -altura,  profundidade);

     // Face lateral direita
     glTexCoord2f(1.0f, 0.0f); glVertex3f( largura, -altura, -profundidade);
     glTexCoord2f(1.0f, 1.0f); glVertex3f( largura,  altura, -profundidade);
     glTexCoord2f(0.0f, 1.0f); glVertex3f( largura,  altura,  profundidade);
     glTexCoord2f(0.0f, 0.0f); glVertex3f( largura, -altura,  profundidade);

     // Face lateral esquerda
     glTexCoord2f(0.0f, 0.0f); glVertex3f(-largura, -altura, -profundidade);
     glTexCoord2f(1.0f, 0.0f); glVertex3f(-largura, -altura,  profundidade);
     glTexCoord2f(1.0f, 1.0f); glVertex3f(-largura,  altura,  profundidade);
     glTexCoord2f(0.0f, 1.0f); glVertex3f(-largura,  altura, -profundidade); 

     glEnd();
}


void desenhar_bloco2( GLfloat altura, GLfloat largura, GLfloat profundidade )
{
     glBegin( GL_QUADS );
     
     // Face frontal
    /* glTexCoord2f(0.0f, 0.0f);      glVertex3f(-largura, -altura,  profundidade);
     glTexCoord2f(largura, 0.0f);   glVertex3f( largura, -altura,  profundidade);
     glTexCoord2f(largura, altura); glVertex3f( largura,  altura,  profundidade);
	 glTexCoord2f(0.0f, altura);    glVertex3f(-largura,  altura,  profundidade);*/

     glTexCoord2f(0.0f, 0.0f);      glVertex3f(-largura+TAM_BLOCO/2, -altura,  profundidade);
     glTexCoord2f(1, 0.0f);   glVertex3f( largura+TAM_BLOCO/2, -altura,  profundidade);
     glTexCoord2f(1, 1); glVertex3f( largura+TAM_BLOCO/2,  altura,  profundidade);
     glTexCoord2f(0.0f, 1);    glVertex3f(-largura+TAM_BLOCO/2,  altura,  profundidade);
         
	 // Face posterior
	 glTexCoord2f(1.0f, 0.0f); glVertex3f(-largura+TAM_BLOCO/2, -altura, -profundidade);
	 glTexCoord2f(1.0f, 1.0f); glVertex3f(-largura+TAM_BLOCO/2,  altura, -profundidade);
	 glTexCoord2f(0.0f, 1.0f); glVertex3f( largura+TAM_BLOCO/2,  altura, -profundidade);
	 glTexCoord2f(0.0f, 0.0f); glVertex3f( largura+TAM_BLOCO/2, -altura, -profundidade);
	 
         // Face superior
	 glTexCoord2f(0.0f, 1.0f); glVertex3f(-largura+TAM_BLOCO/2,  altura, -profundidade);
	 glTexCoord2f(0.0f, 0.0f); glVertex3f(-largura+TAM_BLOCO/2,  altura,  profundidade);
	 glTexCoord2f(1.0f, 0.0f); glVertex3f( largura+TAM_BLOCO/2,  altura,  profundidade);
	 glTexCoord2f(1.0f, 1.0f); glVertex3f( largura+TAM_BLOCO/2,  altura, -profundidade);
	 
	 // Face inferior
	 glTexCoord2f(1.0f, 1.0f); glVertex3f(-largura+TAM_BLOCO/2, -altura, -profundidade);
	 glTexCoord2f(0.0f, 1.0f); glVertex3f( largura+TAM_BLOCO/2, -altura, -profundidade);
	 glTexCoord2f(0.0f, 0.0f); glVertex3f( largura+TAM_BLOCO/2, -altura,  profundidade);
	 glTexCoord2f(1.0f, 0.0f); glVertex3f(-largura+TAM_BLOCO/2, -altura,  profundidade);
	 
	 // Face lateral direita
	 glTexCoord2f(1.0f, 0.0f); glVertex3f( largura+TAM_BLOCO/2, -altura, -profundidade);
	 glTexCoord2f(1.0f, 1.0f); glVertex3f( largura+TAM_BLOCO/2,  altura, -profundidade);
	 glTexCoord2f(0.0f, 1.0f); glVertex3f( largura+TAM_BLOCO/2,  altura,  profundidade);
	 glTexCoord2f(0.0f, 0.0f); glVertex3f( largura+TAM_BLOCO/2, -altura,  profundidade);
	 
	 // Face lateral esquerda
	 glTexCoord2f(0.0f, 0.0f); glVertex3f(-largura+TAM_BLOCO/2, -altura, -profundidade);
	 glTexCoord2f(1.0f, 0.0f); glVertex3f(-largura+TAM_BLOCO/2, -altura,  profundidade);
	 glTexCoord2f(1.0f, 1.0f); glVertex3f(-largura+TAM_BLOCO/2,  altura,  profundidade);
	 glTexCoord2f(0.0f, 1.0f); glVertex3f(-largura+TAM_BLOCO/2,  altura, -profundidade); 
	 
	 glEnd();
}


/*======================= Função desenhar_superficie ====================*/

/**
	Função para desenhar uma superfície plana.

	A função desenha uma superfície que cobre toda a area da matriz (mapa).
        
        @param altura: é a altura da superfície.
        @param largura: é a largura da superfície.
        @param profundidade: é a profundidade da superfície.
        @param altura_mundo: é a altura da superfície em relação ao mundo.
*/

void desenhar_superficie( GLint altura, GLint largura, 
                          GLint profundidade, GLint altura_mundo )
{
    int x, z;
    int x_mundo, z_mundo;
        
    for( x=0; x < LINHAS; x++ )
    {
        for( z=0; z < COLUNAS; z++ )
        { 

             x_mundo = x * TAM_BLOCO;
             z_mundo = z * TAM_BLOCO;

             glPushMatrix();

             glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_amarelo );
             glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );
             glMaterialfv( GL_FRONT, GL_SHININESS, mat_shininess );
             // TODO: Precisa os glMaterialfv ?

             glTranslatef( x_mundo, altura_mundo, z_mundo );

             desenhar_bloco( altura, largura, profundidade );

             glPopMatrix();

        }//for
    }//for

}




/*======================== Função desenhar_parede =======================*/

/**
	Função para desenhar uma parede.

        
        @param altura: é a altura da superfície.
        @param largura: é a largura da superfície.
        @param profundidade: é a profundidade da superfície.
        @param altura_mundo: é a altura da superfície em relação ao mundo.
        @return void
*/

void desenhar_parede( GLint altura, GLint largura, GLint profundidade, 
                               GLint altura_mundo, GLint flag )
{
    int x, z;
    int x_mundo, z_mundo;
        
    for( x=0; x < LINHAS; x++ )
    {
        for( z=0; z < COLUNAS; z++ )
        {
             if( mapa[x][z] == flag )
             {
                 x_mundo = x * TAM_BLOCO;
                 z_mundo = z * TAM_BLOCO;

                 glPushMatrix();

                 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_amarelo );
                 glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular );
                 glMaterialfv( GL_FRONT, GL_SHININESS, mat_shininess );
                 // TODO: Precisa os glMaterialfv ?

                 
                 if(flag==1)
                 {
                     glScalef( 1, 1, 1 );
                     glTranslatef( x_mundo, altura_mundo, z_mundo );
                     desenhar_bloco( altura, largura, profundidade );
                     //parede(1,0);
                 }
                 else
                 {
                    glTranslatef( x_mundo, altura_mundo, z_mundo );
                    glRotatef( 90,0,1,0 );
                    glScalef( 1, 1, 1 );
                    desenhar_bloco( altura, largura, profundidade );
                    //parede(1,0);
                 }

                 glPopMatrix();
             }//if
        }//for
    }//for

}



void inserir_objeto( GLint altura_mundo, GLint objeto )
{
    int x, z;
    int x_mundo, z_mundo;
        
    for( x=0; x < LINHAS; x++ )
    {
        for( z=0; z < COLUNAS; z++ )
        {
             if( mapa[x][z] == objeto )
             {
                 x_mundo = x * TAM_BLOCO;
                 z_mundo = z * TAM_BLOCO;

                 switch( mapa[x][z] )
                 {
                     case PAREDE1:   glPushMatrix();
                               glTranslatef( x_mundo, altura_mundo, z_mundo );
                               parede( 1, 0 );
                               glPopMatrix();
                               break;
                                    
                     case PAREDE2:  glPushMatrix();
                               		glTranslatef( x_mundo, altura_mundo, z_mundo );
                               		parede( 1, 90 );
                               		glPopMatrix();
                               		break;
                                                         
                     case CADEIRA: 	glPushMatrix();
                               		glTranslatef( x_mundo, altura_mundo, z_mundo );
                               		desenhar_cadeira( 5, 0 );
                               		glPopMatrix();
                               		break;
                               		
                     case 4:  glPushMatrix();
                                    glTranslatef( x_mundo, altura_mundo, z_mundo );
                                    parede_corredor1_sala1( 1, 0 );
                                    glPopMatrix();
                                    break;          	
                               		
                               		
                 }
                 
             }
        }
    }

}

/*============================ Função render =============================*/

/**
	Renderizar a cena.

	Função utilizada pela GLUT para renderizar a cena.
*/

void render( void )
{
	int x, z;
	int x_mundo, z_mundo;


	//limpa todos os pixels
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glLoadIdentity();
 
	gluLookAt(         player_x,        player_y,        player_z, 
                  player_x+movimento_x, player_y,   player_z+movimento_z, 
                          0,               1,               0           );

        glPushMatrix(); 
        glBindTexture ( GL_TEXTURE_2D, idTextura[2] ); /* CÃ‰U */
        glTranslatef( player_x, 100, player_z );
        desenhar_bloco( 6000,6000,6000 );

        glPopMatrix();
	

        glBindTexture ( GL_TEXTURE_2D, idTextura[0] );
        /*desenhar_parede( 150, 50, 5, 5 , 1 );           /* PAREDE */
        /*desenhar_parede( 150, 50, 5, 5 , 2 );           /* PAREDE */
        //desenhar_parede( 150, 50, 50, 5 , 1 );           /* PAREDE */
        //desenhar_parede( 150, 50, 50, 5 , 2 );           /* PAREDE */        
        
        glBindTexture ( GL_TEXTURE_2D, idTextura[1] );
        desenhar_superficie( 1, 50, 50,-230);
        
        glBindTexture ( GL_TEXTURE_2D, idTextura[3] );  /* TETO */
        desenhar_superficie( 1, 50, 50,250);
        
        inserir_objeto( 5, CADEIRA ); /* Cadeira */
        inserir_objeto( 2, 4 );
        inserir_objeto( 2, PAREDE1 ); /* Parede  */
        inserir_objeto( 2, PAREDE2 ); /* Parede  */
        
	
        glutSwapBuffers();
}




/*========================= Função select_game_mode ======================*/

/**
	Define a resolução da tela.

	A função testa os modos gráficos para saber qual deles e possível utilizar.
	Primeiro testa o modo 1024x768 com 32 bits de cor e frequencia de atualizacao 
	de 85 Hertz.
	O segundo modo testado é o 800x600 com 32 bits de cor e frequencia de atualizacao de	60 Hertz.
	Se não for possivel iniciar nenhum dos modos, então é criado uma janela normal em		fullscreen.
*/

int select_game_mode( void )
{
	int game_mode;
        
	/* Seleciona o modo de jogo 1024x768. */
	glutGameModeString( "1024x768:32@60" );

	/* Verifica se é possível entrar neste modo */
	if(!glutGameModeGet( GLUT_GAME_MODE_POSSIBLE )) // TODO Tirar o "!"
	{
		glutEnterGameMode();
		return game_mode = true;
	}
	else
	{
		/* Seleciona o modo de jogo 800x600. */
		glutGameModeString( "800x600:32@75" ); 

		/* Verifica se é possível entrar neste modo */
		if (!glutGameModeGet( GLUT_GAME_MODE_POSSIBLE )) // TODO Tirar o "!"
		{
			glutEnterGameMode();
			return game_mode = true;
		}
		else /* Se o modo game não é possivel */
		{
			/* Define o nome da janela */
			glutCreateWindow( "NOME DO TRABALHO" );//TODO trocar nome.

			/* Cria janela normal fullscreen */
			glutFullScreen();
			return game_mode = false;
		}
	}
}



/*============================ Função keyboard ===========================*/

/**
	Função para controlar as teclas pressionadas no teclado.
	
	Estabelece a função callback que é chamada pela GLUT cada vez que uma tecla que gera cÃ³digo 
	ASCII é pressionada. Tambem é passado a posição do mouse no momento em que foi pressionada a tecla.
	Teclas:
	ESC: Sair do Programa
	TODO Escrever as funções das outras teclas.

	@param key: Tecla pressionada no teclado.
	@param x: Posição x do mouse quando a tecla foi pressionada.
	@param y: Posição y do mouse quando a tecla foi pressionada.
*/

void keyboard( unsigned char key, int x, int y )
{
    float rad;
    
    switch( key )
    {
            /* Tecla ESC */
            case 27:exit( 0 ); /* Sai do programa. */
            break;

            case 115://letra s 

                    if( pode_mover( player_x, player_z, - movimento_x, -movimento_z ) )
                    {
                        player_x -= movimento_x;
                        player_z -= movimento_z;
                    }
                        break;


            case 119://letra w 

                    if( pode_mover( player_x, player_z,  movimento_x, movimento_z ) )
                    {
                        player_x += movimento_x;
                        player_z += movimento_z;
                    }
            break;

            case 97://letra a 

                    angulo -= 10;

                    if( angulo < 0 ) 
                        angulo +=360;

                    rad =  (float) ( 3.14159 * angulo / 180.0f );

                    movimento_x =  cos( rad ) * PASSO;
                    movimento_z =  sin( rad ) * PASSO;
            break;


            case 100://letra d 

                    angulo += 10;

                    if(angulo >= 360)
                        angulo -=360;

                    rad =  (float) ( 3.14159 * angulo / 180.0f );

                    movimento_x = cos( rad ) * PASSO;
                    movimento_z = sin( rad ) * PASSO;

            break;   
    }
    glutPostRedisplay();

}



/*========================== Função special_keys =========================*/

/**
	Função para manipular as teclas especias do teclado.

	Estabelece a função callback que é chamada pela GLUT cada vez que uma tecla que gera cÃ³digo 
	não-ASCII é pressionada. Tambem é passado a posição do mouse no momento em que foi pressionada a tecla.
	Teclas:
	TODO: Escrever as funções das teclas.
	
	@param key: Tecla pressionada no teclado.
	@param x: Posição x do mouse quando a tecla foi pressionada.
	@param y: Posição y do mouse quando a tecla foi pressionada.
*/

void special_keys( int key, int x, int y )
{
	float rad;

	switch ( key ) 
	{
		case GLUT_KEY_DOWN: 
                    
				//if( pode_mover( player_x, player_z, - movimento_x, -movimento_z ) )
				{
					player_x -= movimento_x;
					player_z -= movimento_z;
				}
		break;
	  
		case GLUT_KEY_UP: 

				//if( pode_mover( player_x, player_z,  movimento_x, movimento_z ) )
				{
					player_x += movimento_x;
					player_z += movimento_z;
				}
		break;
  
		case GLUT_KEY_LEFT: 
	
				angulo -= 10;

				if( angulo < 0 )
					angulo +=360;
				
				rad =  (float) ( 3.14159 * angulo / 180.0f );

				movimento_x =  cos( rad ) * PASSO*2;
				movimento_z =  sin( rad ) * PASSO*2;
		break;

		case GLUT_KEY_RIGHT: 

				angulo += 10;

				if( angulo >= 360 )
					angulo -=360;
	 
				rad =  (float) ( 3.14159 * angulo / 180.0f );

				movimento_x = cos( rad ) * PASSO*2;
				movimento_z = sin( rad ) * PASSO*2;
		break;
	 
	}
        glutPostRedisplay();
}



/*=============================== Função main ============================*/

/**
	Função para controlar a posição do cursor na tela.

	A função recebe como parametros as coordenadas do cursor na tela, movimentando
	a camera de acordo com o movimento feito com o cursor.

	@param x: Posição x do mouse na tela.
	@param y: Posição y do mouse na tela.
*/

void mouse_func( int x, int y )
{
    float rad;
    
    int diferenca_x = x - x_anterior; //check the difference between the current x and the last x position
    int diferenca_y = y - y_anterior; //check the difference between the current y and the last y position

    x_anterior = x; //set lastx to the current x position
    y_anterior = y; //set lasty to the current y position

    //movimento_z += (float) diferenca_x; //set the xrot to xrot with the addition of the difference in the y position
    //movimento_x += (float) diferenca_y; //set the xrot to yrot with the addition of the difference in the x position
	 //TODO: Implementar função para movimentar a camera com o mouse
    if( diferenca_x > 0 )
    {
        angulo += 5;

        if( angulo >= 360 )
                angulo -=360;

        rad =  (float) ( 3.14159 * angulo / 180.0f );

        movimento_x = cos( rad ) * PASSO;
        movimento_z = sin( rad ) * PASSO;
    }
    else
    {
        angulo -= 5;

        if( angulo < 0 )
                angulo +=360;

        rad =  (float) ( 3.14159 * angulo / 180.0f );

        movimento_x =  cos( rad ) * PASSO;
        movimento_z =  sin( rad ) * PASSO;
    }
    
    glutPostRedisplay();
}



/*=============================== Função main ============================*/

/**
	Programa principal.
*/

int main( int argc, char **argv )
{
	int game_mode;

	glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
    
	/* --------- Define a resolução da tela ------------ */
	game_mode = select_game_mode();

	inicializar();							/* Inicializa as variáveis do OpenGL */
	glutDisplayFunc( render );				/* Função callback de renderização   */
	glutKeyboardFunc( keyboard );			/* Função callback do teclado 		 */
	glutSpecialFunc( special_keys );		/* Função callback teclas especiais  */
	//glutPassiveMotionFunc( mouse_func );	/* Função callback posição do mouse  */
	glutMainLoop();							/* Inicia a máquina de estados       */
	
	return 0;
}





